﻿using Microsoft.Win32;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace WebPageDownloader
{
    /// <summary>
    /// MainWindow.xaml 的交互逻辑
    /// </summary>
    public partial class MainWindow : Window
    {
        static readonly Guid SID_SWebBrowserApp = new Guid("0002DF05-0000-0000-C000-000000000046");
        public MainWindow()
        {
            InitializeComponent();

            browser.LoadCompleted += OnBrowserLoadCompleted;
        }

        private void OnBrowserLoadCompleted(object sender, NavigationEventArgs e)
        {
            IServiceProvider serviceProvider = (IServiceProvider)browser.Document;
            Guid serviceGuid = SID_SWebBrowserApp;
            Guid iid = typeof(SHDocVw.IWebBrowser2).GUID;
            SHDocVw.IWebBrowser2 myWebBrowser2 = (SHDocVw.IWebBrowser2)serviceProvider.QueryService(ref serviceGuid, ref iid);
            //Hook new window event
            SHDocVw.DWebBrowserEvents_Event wbEvents = (SHDocVw.DWebBrowserEvents_Event)myWebBrowser2;
            wbEvents.NewWindow += new SHDocVw.DWebBrowserEvents_NewWindowEventHandler(OnWebBrowserNewWindow);
        }

        private void OnWebBrowserNewWindow(string URL, int Flags, string TargetFrameName, ref object PostData, string Headers, ref bool Processed)
        {
            Processed = true;
            urlTextBox.Text = URL;
            browser.Navigate(URL);
        }

        private void OnUrlTextBoxKeyUp(object sender, KeyEventArgs e)
        {
            if (e.Key != Key.Enter)
            {
                return;
            }
            var url = urlTextBox.Text.Trim();            
            if(!Uri.TryCreate(url, UriKind.RelativeOrAbsolute, out Uri uri))
            {
                MessageBox.Show("请输入正确网址。", "错误");
                return;
            }
            if (!url.Contains(":"))
            {
                url = "http://" + url;
            }
            browser.Navigate(url);            
        }

        private void OnNavigating(object sender, NavigatingCancelEventArgs e)
        {
            progressTextBlock.Visibility = Visibility.Visible;
            browser.Visibility = Visibility.Hidden;
            if (urlTextBox.Text != e.Uri.ToString())
            {
                urlTextBox.Text = e.Uri.ToString();
            }
        }

        private void OnNavigated(object sender, NavigationEventArgs e)
        {
            progressTextBlock.Visibility = Visibility.Collapsed;
            browser.Visibility = Visibility.Visible;
        }

        private void OnBackButtonClick(object sender, RoutedEventArgs e)
        {
            if (browser.CanGoBack)
            {
                browser.GoBack();                
            }
        }

        private void OnForwardButtonClick(object sender, RoutedEventArgs e)
        {
            if (browser.CanGoForward)
            {                
                browser.GoForward();                
            }
        }

        private void OnRefreshButtonClick(object sender, RoutedEventArgs e)
        {
            if (!string.IsNullOrWhiteSpace(urlTextBox.Text))
            {
                browser.Refresh();
            }
        }

        private void OnSaveButtonClick(object sender, RoutedEventArgs e)
        {
            if (browser.IsLoaded && browser.Document != null)
            {
                dynamic document = browser.Document;                
                var content = document.GetElementsByTagName("HTML")[0].OuterHtml;
                if (DisableJavaScriptCheckBox.IsChecked == true)
                {
                    content = ReplaceString(content, "<javascript", "<!--<javascript");
                    content = ReplaceString(content, "</javascript>", "</javascript>-->");
                    content = ReplaceString(content, "<script", "<!--<script");
                    content = ReplaceString(content, "</script>", "</script>-->");
                }
                OpenFileDialog fileDialog = new OpenFileDialog();
                fileDialog.Filter = "网页文件|*.html;*.htm";
                fileDialog.Multiselect = false;
                fileDialog.CheckFileExists = false;
                fileDialog.CheckPathExists = true;
                var result = fileDialog.ShowDialog(this);
                if (true == result)
                {
                    using (var fileStream = File.Create(fileDialog.FileName))
                    {
                        using (var writer = new StreamWriter(fileStream))
                        {
                            writer.Write(content);
                            writer.Flush();
                        }                        
                    }
                    if (MessageBox.Show($"文件已保存到路径\n{fileDialog.FileName}\n需要加载吗？", "提示", MessageBoxButton.YesNo) == MessageBoxResult.Yes)
                    {
                        urlTextBox.Text = fileDialog.FileName;
                        browser.Navigate(urlTextBox.Text);
                    }                    
                }
            }
            else
            {
                MessageBox.Show("请等待页面加载后再保存。", "错误");
            }
        }

        private string ReplaceString(string rawContent, string regEx, string replacement)
        {
            var regex = new Regex(regEx, RegexOptions.Compiled | RegexOptions.IgnoreCase);
            return regex.Replace(rawContent, replacement);
        }

        private void OnPrintButtonClick(object sender, RoutedEventArgs e)
        {
            dynamic document = browser.Document;
            if(document != null)
            {
                document.execCommand("Print", false, null);
            }
        }
    }

    /// <summary>
    /// Reference to COM component named "Microsoft Internet Controls" to hook new window event
    /// </summary>
    [ComImport, InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
    [Guid("6d5140c1-7436-11ce-8034-00aa006009fa")]
    internal interface IServiceProvider
    {
        [return: MarshalAs(UnmanagedType.IUnknown)]
        object QueryService(ref Guid guidService, ref Guid riid);
    }
}
